//
//  FQDPraiseHistory.m
//  FakeQDaily
//
//  Created by mewxiv on 9/5/16.
//  Copyright © 2016 Xensius. All rights reserved.
//

#import "FQDPraiseHistory.h"
#import "FQDDatabase.h"
#import "FQDRestModel.h"
#import "QDailyAPI.h"

NSString *const kPraiseTypeArticle = @"article";
NSString *const kPraiseTypeComment = @"comment";

static NSString *const kPraiseHistoryTableName = @"fqd_priase_history";

@implementation FQDPraiseHistoryItem

@end

@interface FQDPraiseHistory ()

@property (nonatomic, strong) NSCache *historyCache;

@end

@implementation FQDPraiseHistory

+ (instancetype)sharedHistory
{
    static FQDPraiseHistory *history;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        history = [[self class] new];
    });
    return history;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self commonInit];
    }
    return self;
}

- (void)commonInit
{
    NSDictionary *columns = @{
        @"qdID" : @"VARCHAR PRIMARY KEY",
        @"praise" : @"BOOLEAN",
        @"praise_type" : @"VARCHAR",
        @"user_id" : @"VARCHAR",
        @"create_time" : @"DOUBLE",
    };
    
    FQDDatabase *database = [FQDDatabase sharedDatabase];
    [database createTableIfNotExist:kPraiseHistoryTableName columns:columns];
}

- (void)praiseWithItem:(FQDPraiseHistoryItem *)praiseItem originalPraiseCount:(NSInteger)originalPraiseCount
     updatePraiseCountBlock:(void (^)(NSInteger praiseCount))updatePraiseCountBlock
{
    NSInteger praiseCountBefore = originalPraiseCount;
    BOOL praisedBefore = [self userHasPraised:praiseItem.qdID userId:praiseItem.userId];
    BOOL praisedNow = !praisedBefore;
    
    [self savePraiseItem:praiseItem toLocalStorage:NO];

    NSInteger praiseCount = (praisedNow) ? originalPraiseCount + 1 : originalPraiseCount - 1;
    if (updatePraiseCountBlock) {
        updatePraiseCountBlock(praiseCount);
    }

    // genre为1表示点赞，为2表示取消点赞
    NSInteger genre = (praisedNow) ? 1 : 2;
    [[QDailyAPI sharedAPI] praisePost:praiseItem.qdID genre:genre praiseType:praiseItem.praiseType
     completion:^(id responseObject, NSError *error) {
        if (responseObject) {
            NSNumber *status = responseObject[@"meta"][@"status"];
            BOOL success = ([status integerValue] == 200);
            NSNumber *qdID = responseObject[@"response"][@"target_id"];
            NSNumber *praise_count = responseObject[@"response"][@"praise_count"];

            if (success && [praiseItem.qdID isEqualToString:[qdID stringValue]]) {
                FQDLog(@"success praise");
                NSInteger newPraiseCount = [praise_count integerValue];
                BOOL praise = [self userHasPraised:praiseItem.qdID userId:praiseItem.userId];
                praiseItem.praised = praise;
                [self savePraiseItem:praiseItem toLocalStorage:YES];
                if (updatePraiseCountBlock) {
                    updatePraiseCountBlock(newPraiseCount);
                }
            }
        } else {
            // praise failed, revert
            if (updatePraiseCountBlock) {
                updatePraiseCountBlock(praiseCountBefore);
            }
            praiseItem.praised = praiseCountBefore;
            [self savePraiseItem:praiseItem toLocalStorage:NO];
            FQDLog(@"Error praise article:%@", [error localizedDescription]);
        }
    }];
}

- (void)savePraiseItem:(FQDPraiseHistoryItem *)praiseItem toLocalStorage:(BOOL)saveToLocal;
{
    
    if (saveToLocal) {
        if (![self updatePraiseHistoryItem:praiseItem]) {
            [self insertPraiseHistoryItem:praiseItem];
        }
    }
    
    NSMutableDictionary *items = [self praiseItemsForUserId:praiseItem.userId];
    items[praiseItem.qdID] = @(praiseItem.praised);
}

- (BOOL)updatePraiseHistoryItem:(FQDPraiseHistoryItem *)item
{
    NSDictionary *updateValues = @{
        @"praise" : @(item.praised),
    };
    NSString *whereCondition = [NSString stringWithFormat:@"user_id = '%@' AND qdID = '%@'", item.userId, item.qdID];
    FQDDatabase *database = [FQDDatabase sharedDatabase];
    BOOL hasChanges = [database updateTable:kPraiseHistoryTableName
                            setColumnValues:updateValues
                             whereCondition:whereCondition];
    return hasChanges;
}

- (void)insertPraiseHistoryItem:(FQDPraiseHistoryItem *)item
{
    NSTimeInterval createTime = [[NSDate date] timeIntervalSince1970];
    NSDictionary *columnValues = @{
        @"qdID" : item.qdID,
        @"praise" : @(item.praised),
        @"praise_type" : item.praiseType,
        @"user_id" : item.userId,
        @"create_time" : @(createTime),
    };
    
    FQDDatabase *database = [FQDDatabase sharedDatabase];
    [database insertIntoTable:kPraiseHistoryTableName columnValues:columnValues];
}

- (BOOL)userHasPraised:(NSString *)qdID userId:(NSString *)userId
{
    NSMutableDictionary *items = [self praiseItemsForUserId:userId];
    NSNumber *praise = items[qdID];
    
    if (!praise) {
        FQDDatabase *database = [FQDDatabase sharedDatabase];
        NSString *condition = [NSString stringWithFormat:@"qdID = '%@' AND user_id = '%@'", qdID, userId];
        praise = [database selectColumn:@"praise"
                                        fromTable:kPraiseHistoryTableName
                                   whereCondition:condition];
        items[qdID] = praise;
    }
    return [praise boolValue];
}

- (NSMutableDictionary *)praiseItemsForUserId:(NSString *)userId
{
    NSMutableDictionary *items = [self.historyCache objectForKey:userId];
    if (!items) {
        items = [NSMutableDictionary dictionary];
        [self.historyCache setObject:items forKey:userId];
    }
    return items;
}

- (NSCache *)historyCache
{
    if (!_historyCache) {
        _historyCache = [[NSCache alloc] init];
    }
    return _historyCache;
}

@end
